home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 27 / CU Amiga Magazine's Super CD-ROM 27 (1998)(EMAP Images)(GB)[!][issue 1998-10].iso / CUCD / Magazine / Networking / EmuNet09b / socket / stest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-22  |  29.8 KB  |  967 lines

  1. /*========================================================*/
  2. /*-SOURCE OF     (stest.c)  ------------------------------*/
  3. /*--------------------------------------------------------*/
  4. /* (C) Jul/1998  Dr. Adil Temel    (atemel@hotmail.com)      */
  5. /*--------------------------------------------------------*/
  6. /* stest.c      : BSD Socket test & RAW transfer speed    */
  7. /* Created      : 19980710 03:41:42 Fri                */
  8. /* Last Modified: 19980712 19:06:52 Sun              */
  9. /*========================================================*/
  10.  
  11. #define VERSION "0.5"
  12. /*--------------------------------------------------------*/
  13. #define PORTNUM 50000         /* random port number, we need something */
  14. /*--------------------------------------------------------*/
  15. #define MAXDATA (2*1024*1024L)  /* 1024K transfer */
  16. /*--------------------------------------------------------*/
  17. #define MAXBUF (1024L)          /* Unit of transfer */
  18. /*--------------------------------------------------------*/
  19. #define DUMPLEN (0x40)          /* dump last received/sent data */
  20. /*--------------------------------------------------------*/
  21. #include <errno.h>
  22. #include <signal.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <time.h>
  26.  
  27. #include <unistd.h>
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <sys/wait.h>
  31. #include <netinet/in.h>
  32. #include <netdb.h>
  33.  
  34. /*--------------------------------------------------------*/
  35. #ifdef AMIGA
  36. /*--------------------------------------------------------*/
  37. #include <exec/types.h>
  38. /*--------------------------------------------------------*/
  39. #else
  40. typedef signed long     LONG;        /* signed 32-bit quantity */
  41. typedef unsigned long    ULONG;        /* unsigned 32-bit quantity */
  42. typedef signed short     WORD;        /* signed 16-bit quantity */
  43. typedef unsigned short    UWORD;        /* unsigned 16-bit quantity */
  44. typedef signed char     BYTE;        /* signed 8-bit quantity */
  45. typedef unsigned char    UBYTE;        /* unsigned 8-bit quantity */
  46. #endif
  47.  
  48.  
  49.  
  50. #define COMPILENAME "SocketTest"
  51. /*--------------------------------------------------------*/
  52. #define PROGRAMNAME COMPILENAME " V" VERSION
  53. /*--------------------------------------------------------*/
  54. #define COPYRIGHT  PROGRAMNAME" Test BSD socket communication.\n"  \
  55.            "Written by Dr. Adil Temel (E-Mail: atemel@hotmail.com) (C) 1998\r\n"
  56. /*--------------------------------------------------------*/
  57.  
  58. #ifndef MAXHOSTNAME
  59. #define MAXHOSTNAME 256
  60. #endif
  61. #define RETSIGTYPE void
  62.  
  63. /*--------------------------------------------------------*/
  64. long ntol(char *s);
  65. char sw_server=0,sw_quiet=0,sw_verbose=0,sw_random=0;
  66. char sw_debug=0,sw_checksum=0,sw_readback=0;
  67. char sw_keepalive=0;
  68.  
  69. char *kw_hostname=NULL;
  70.  
  71. /*--------------------------------------------------------*/
  72. unsigned short int portnum=PORTNUM;
  73. /*--------------------------------------------------------*/
  74. long maxbuf=MAXBUF,maxdata=MAXDATA;
  75. char *bufptr=NULL;
  76.  
  77. /*--------------------------------------------------------*/
  78. #ifndef TRUE
  79. #define TRUE 1
  80. #define FALSE 0
  81. #endif
  82. /*--------------------------------------------------------*/
  83. RETSIGTYPE fireman(int x);
  84. int get_connection(int s);
  85. int establish(unsigned short portnum);
  86. int call_socket(char *hostname, unsigned short portnum);
  87. int mygethostname(char *hostname,int maxlen);
  88. struct hostent *mygethostent(char *hostname);
  89. /*--------------------------------------------------------*/
  90. int send_long(int s, long l);
  91. int send_word(int s, short l);
  92. int send_byte(int s, char l);
  93. /*--------------------------------------------------------*/
  94. int  get_long(int s, long *l);
  95. int  get_word(int s, short *l);
  96. int  get_byte(int s, char *l);
  97. /*--------------------------------------------------------*/
  98. int read_data (int s,char *buf,int n);
  99. int write_data(int s,char *buf,int n);
  100. /*--------------------------------------------------------*/
  101. int  receive_data(int s);
  102. int  send_data(void);
  103.  
  104. /*--------------------------------------------------------*/
  105. void CurrentTime(ULONG *s,ULONG *m);
  106. void DiffTime(ULONG *s1,ULONG *m1,ULONG s2,ULONG m2);
  107. char *SPrintTime(ULONG s,ULONG m);
  108. /*--------------------------------------------------------*/
  109. long  memrnd(void *d,long sd,long len);
  110. void  memcsum(void *d,ULONG *cs,long len);
  111. void  memdump(void *s,long len,long adr);
  112. char  *dumpadr(char *s,long len);
  113.  
  114. unsigned long RangeSeed(unsigned long s);
  115. unsigned short int RangeRand(int d6);
  116. /*--------------------------------------------------------*/
  117. int main(int argc,char **argv)
  118. int s, t;
  119. int i,x,ret;
  120. char *karg,skip,argused;
  121. printf(COPYRIGHT);
  122. //printf(COMPILEDATE);
  123. if(argc>=2)
  124. if(argv[1][0]=='?')
  125.   {
  126.     usage:
  127.     printf("Usage: "COMPILENAME" [OPTIONS]\n");
  128.     printf("Available options: (use with prefix - or /)\n");
  129.     printf("----------------------------------------------\n");
  130.     printf(" -s               Run as server\n");
  131.     printf(" -pPORTNUM        Use this portnumber\n");
  132.     printf(" -nHOSTNAME       Call which computer\n");
  133.     printf(" -bMAXBUF_K       Buffer sizeK    [1K]\n");
  134.     printf(" -eMAXDATA_K      Send data sizeK     [1024K]\n");
  135.     printf(" -r               Use randomized data (hardly compressible)\n");
  136.     printf(" -c               Use simple checksum\n");
  137.     printf(" -f               Read back written data\n");
  138.     printf(" -k               Use socket option: SO_KEEPALIVE\n");
  139.     printf(" -d               DEBUG\n");
  140.     exit(0);
  141.   }
  142. for(i=1;i<argc;i++)
  143.  if(argv[i][0]=='-' || argv[i][0]=='/')
  144.   {
  145.     karg=&argv[i][2];skip=0;argused=0;
  146.     if(!*karg)
  147.      {
  148.          karg=argv[i+1];skip=1;
  149.          if(!karg || *karg=='-' || *karg=='/') {karg="";skip=0;}
  150.      }
  151.     if(!karg) karg="";/* no NULL ptr */
  152.     switch(argv[i][1]|0x20)
  153.      {
  154.        case 'h':
  155.        case '?': goto usage;
  156.        case 'p': portnum=ntol(karg);argused=1;
  157.          if(!portnum) portnum=PORTNUM;
  158.          break;
  159.        case 'b': maxbuf=ntol(karg)*1024L;argused=1;
  160.          if(maxbuf<=0 || maxbuf>(512*1024L)) maxbuf=MAXBUF;
  161.          break;
  162.        case 'e': maxdata=ntol(karg)*1024L;argused=1;
  163.          if(maxdata<=0 || maxdata>(16384*1024L)) maxdata=MAXDATA;
  164.          break;
  165.        case 'n': kw_hostname=karg;argused=1;break;
  166.        case 'k': sw_keepalive=TRUE;break;
  167.        case 'c': sw_checksum=TRUE;break;
  168.        case 'f': sw_readback=TRUE;break;
  169.        case 'r': sw_random=TRUE;break;
  170.        case 's': sw_server=TRUE;break;
  171.        case 'd': sw_debug =TRUE;break;
  172.        case 'v': sw_verbose=TRUE;sw_quiet=FALSE;break;
  173.        case 'q': sw_verbose=FALSE;sw_quiet=TRUE;break;
  174.          break;
  175.        default:  printf("Unknown option %s ignored\n",argv[i]);
  176.      }
  177.     if(argused) i+=skip;
  178.   }
  179. bufptr=malloc(maxbuf);
  180. if(!bufptr)
  181.   {
  182.     fprintf(stderr,"Can't get %ld buffer.\n",maxbuf);
  183.     exit(1);
  184.   }
  185. printf("Using portnum %d , buf %ldK , data %ldK\n",(long) portnum,maxbuf>>10L,maxdata>>10L);
  186. if(!sw_server)
  187.  {
  188.     send_data();
  189.     exit(0);
  190.  }
  191. printf("Running as server..\n");
  192. if ((s= establish(portnum)) < 0) {  /* plug in the phone */
  193.     perror("establish");
  194.     exit(1);
  195.   }
  196. #if 0
  197.  signal(SIGCHLD, fireman);           /* this eliminates zombies */
  198. #endif
  199.   printf("Waiting for connections.\n");
  200.  
  201.   for (;;) {                          /* loop for phone calls */
  202.     if ((t= get_connection(s)) < 0) { /* get a connection */
  203.       if (errno == EINTR)             /* EINTR might happen on accept(), */
  204.         continue;                     /* try again */
  205.       perror("accept");               /* bad */
  206.       exit(1);
  207.     }
  208. #if 0 //#ifndef AMIGA
  209.     switch(fork()) {                  /* try to handle connection */
  210.     case -1 :                         /* bad news.  scream and die */
  211.       perror("fork");
  212.       close(s);
  213.       close(t);
  214.       exit(1);
  215.     case 0 :                          /* we're the child, do something */
  216.       close(s);
  217.       receive_data(t);
  218.       exit(0);
  219.     default :                         /* we're the parent so look for */
  220.       close(t);                       /* another connection */
  221.       continue;
  222.     }
  223. #else
  224.       receive_data(t);
  225.       close(t);
  226. #endif
  227.  
  228.   }
  229. }
  230.  
  231. /* as children die we should get catch their returns or else we get
  232.  * zombies, A Bad Thing.  fireman() catches falling children.
  233.  */
  234. RETSIGTYPE fireman(int x)
  235. {
  236.   //printf("fireman started.\n");
  237.   while (waitpid(-1,NULL,WNOHANG) > 0)  ;
  238.   //printf("fireman finished.\n");
  239. }
  240.  
  241.  
  242. long bytes_msec(ULONG b,ULONG s,ULONG m)
  243. {
  244. m=m/1000L+s*1000L;if(!m) m=1;
  245. b/=m;
  246. return b;
  247. }
  248. /*--------------------------------------------------------*/
  249. void say_result(char *info,ULONG tot,ULONG totb, ULONG s1,ULONG m1,ULONG s2,ULONG m2)
  250. {
  251. ULONG b;
  252. char *rwmode;
  253. DiffTime(&s1,&m1,s2,m2);
  254. tot+=totb;b=bytes_msec(tot,s1,m1);
  255. if(totb) 
  256.   {
  257.     rwmode= sw_server ? "READ/WRITE":"WRITE/READ";
  258.   }
  259. else
  260.   {
  261.     rwmode= sw_server ? "WRITE":"READ";
  262.   }
  263. printf("%s: total %ldK (%ld bytes) %s (%ld bytes/msec %ld bytes/sec %ldK/sec ).\n",
  264.         info,
  265.             tot/1024L,tot,rwmode,
  266.         b,b*1000L,b*1000L/1024L);
  267. printf("%s: elapsed Time ticks: %s\n",info,SPrintTime(s1,m1));
  268. }
  269.  
  270. /*--------------------------------------------------------*/
  271. #if 0
  272. /*
  273. After you create a socket to get calls, you must wait for calls to that
  274. socket. The accept() function is used to do this. Calling accept() is
  275. analogous to picking up the telephone if it's ringing. Accept() returns a
  276. new socket which is connected to the caller.
  277.  
  278. The following function can be used to accept a connection on a socket that
  279. has been created using the establish() function above:
  280. */
  281.  
  282. #endif
  283. /*--------------------------------------------------------*/
  284. #define PARMF_RAND     (1L<<0)
  285. #define PARMF_CSUM     (1L<<1)
  286. #define PARMF_RBACK    (1L<<2)
  287. #define PARMF_PSIG    (1L<<7) /* parameter id */
  288. /*--------------------------------------------------------*/
  289. #define START_BYTE     (0xAC)
  290. /*--------------------------------------------------------*/
  291. int send_data(void)
  292. {
  293.    int s,i,c;
  294.    ULONG l;
  295.    ULONG s1,s2,m1,m2;
  296.    ULONG len,tot=0,totb=0,csum=0,rs=0;
  297.    UBYTE x=0;
  298.    char  name[MAXHOSTNAME+1];
  299.    UBYTE parm=PARMF_PSIG;
  300.    if(sw_random  ) parm|=PARMF_RAND;
  301.    if(sw_checksum) parm|=PARMF_CSUM;
  302.    if(sw_readback) parm|=PARMF_RBACK;
  303.  
  304.    if(kw_hostname) strcpy(name,kw_hostname);
  305.    else mygethostname(name, MAXHOSTNAME);           /* who are we? */
  306.   
  307.    printf("send_data: sending to %s port %d\n",name,(long)portnum);
  308.    if( (s=call_socket(name,portnum)) <0)
  309.    {
  310.       fprintf(stderr,"cannot connect.\n");
  311.       return -1;
  312.     }
  313.    len=maxdata;
  314.    printf("send_data: socket %d , sending %ld\n",s,len);
  315.    if(send_long(s,len)<0)
  316.     {
  317.       error:
  318.       printf("send_data: failed to send parameter!\n");
  319.       goto fin;
  320.     }
  321.    if(send_byte(s,parm)>=0)
  322.     {
  323.        if(parm& PARMF_RAND)  printf("send_data: will send random data.\n");
  324.        if(parm& PARMF_CSUM)  printf("send_data: will use checksum.\n");
  325.        if(parm& PARMF_RBACK) printf("send_data: will read back sent data\n");
  326.     }  else goto error;
  327.     len=maxdata;
  328.     if(len && len<maxbuf) l=len;else l=maxbuf;
  329.     if(!len) len=MAXBUF;/* default send length */
  330.     /* Dummy data */
  331.     if(parm & PARMF_RAND)
  332.      {
  333.          rs=memrnd(bufptr,time(NULL),l);
  334.          if(send_long(s,rs)<0) goto error;
  335.          printf("send_data: using random seed 0x%08lx\n",rs);
  336.      }
  337.     else  memset(bufptr,x++,l);
  338.     if(send_byte(s,START_BYTE)<0) goto error;
  339.     CurrentTime(&s1,&m1);
  340.     while(len && (c=write_data(s,bufptr,l)) >0 )
  341.      {
  342. #if 0
  343.         if(sw_random) memrnd(bufptr,-1,l);
  344.         else          memset(bufptr,x++,l);
  345. #endif
  346.     if(parm&PARMF_CSUM) memcsum(bufptr,&csum,l);
  347.         if(parm&PARMF_RBACK)
  348.       {
  349.         if(read_data(s,bufptr,c)<c)
  350.          {
  351.            printf("send_data: cannot read %d\n",c);
  352.            break;
  353.          } else totb+=c;
  354.           }
  355.         tot+=c;len-=c;
  356.         if(len<maxbuf) l=len;else l=maxbuf;
  357.      }
  358.     CurrentTime(&s2,&m2);
  359.     memdump(bufptr+c-DUMPLEN,DUMPLEN,tot-DUMPLEN);
  360.     say_result("send_data",tot,totb,s1,m1,s2,m2);
  361.     if(parm&PARMF_CSUM) 
  362.     {
  363.         printf("send_data: checksum 0x%08lx\n",csum);
  364.         send_long(s,csum);
  365.     }
  366. fin:
  367.   close(s);
  368.   printf("send_data: socket closed.\n");
  369.   return 0;
  370. }
  371.  
  372. /*--------------------------------------------------------*/
  373. /* this is the function that plays with the socket.it will*/
  374. /* be called after getting a connection.          */
  375. /*--------------------------------------------------------*/
  376. int receive_data(int s)
  377. {
  378.    int i,c;
  379.    ULONG l;
  380.    ULONG s1,s2,m1,m2;
  381.    ULONG len,tot=0,totb=0,csum=0,rs=0;
  382.    UBYTE parm=0;
  383.    UBYTE start;
  384.    printf("receive_data: socket %d\n",s);
  385.    if(get_long(s,&len)<0)
  386.     { 
  387.       error:
  388.       printf("receive_data: failed to read parameter!\n");
  389.       goto fin;
  390.     }
  391.     printf("receive_data: expecting %ld bytes\n",len);
  392.     if(get_byte(s,&parm)>=0)
  393.      {    
  394.        if(!(parm&PARMF_PSIG)) {printf("receive_data: wrong parameter received.\n");goto fin;}
  395.        if(parm&PARMF_RAND)  printf("receive_data: will receive random data.\n");
  396.        if(parm&PARMF_CSUM)  printf("receive_data: will use checksum.\n");
  397.        if(parm&PARMF_RBACK) printf("receive_data: will write back received data\n");
  398.      }
  399.     else goto error;
  400.  
  401.     if(parm&PARMF_RAND) 
  402.      {
  403.        if(get_long(s,&rs)<0) goto error;
  404.        printf("receive_data: remote random seed 0x%08lx\n",rs);
  405.      }
  406.     if(len && len<maxbuf) l=len;else l=maxbuf;
  407.     if(!len) len=0xFFFFFFFF;
  408.     if(get_byte(s,&start)) goto error;
  409.     if(start!=START_BYTE)
  410.      {
  411.     printf("receive_data: wrong start byte 0x%02lX (expecting 0x%02lX)\n",
  412.             start,START_BYTE);
  413.         goto error;
  414.       }
  415.     CurrentTime(&s1,&m1);
  416.     while(len && (c=read_data(s,bufptr,l)) >0 )
  417.      {
  418.     if(parm&PARMF_CSUM) memcsum(bufptr,&csum,l);
  419.         if(parm&PARMF_RBACK)
  420.       {
  421.         if(write_data(s,bufptr,c)<c)
  422.          {
  423.            printf("receive_data: cannot re-send received data %d\n",c);
  424.            break;
  425.          } else totb+=c;
  426.           }
  427.  
  428.         tot+=c;len-=c;
  429.         if(len<maxbuf) l=len;else l=maxbuf;
  430.      }
  431.      CurrentTime(&s2,&m2);
  432.      memdump(bufptr+c-DUMPLEN,DUMPLEN,tot-DUMPLEN);
  433.      say_result("receive_data",tot,totb,s1,m1,s2,m2);
  434.      if(parm&PARMF_CSUM) 
  435.     {
  436.       ULONG rsum;
  437.       get_long(s,&rsum);
  438.       printf("receive_data: checksum remote 0x%08lx%s0x%08lx %s\n",
  439.         rsum,rsum==csum ? "==":"!=",csum, rsum==csum ? "OK!":"FAILURE!!");
  440.     }
  441. fin:
  442. printf("receive_data: exit\n");
  443. return 0;
  444. }
  445. /*--------------------------------------------------------*/
  446. int ONE = 1;
  447. /*--------------------------------------------------------*/
  448. int sokeepalive(int s)
  449. {
  450. int r;
  451. printf("sokeepalive: keeping %d alive\n",s);
  452. r= setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &ONE, sizeof ONE);
  453. printf("sokeepalive: setsockopt returned %d\n",r);
  454. return r;
  455. }
  456.  
  457. /*--------------------------------------------------------*/
  458. /* send a long lvalue across network              */
  459. /*--------------------------------------------------------*/
  460. int send_long(int s, long l)
  461. {
  462.    l=htonl(l);/* host to network long */
  463.    if(write_data(s,(char *)&l,sizeof(long))==sizeof(long)) return 0;
  464.    return -1;/* Failed */
  465. }
  466. /*--------------------------------------------------------*/
  467. /* get  a long lvalue from network              */
  468. /*--------------------------------------------------------*/
  469. int get_long(int s, long *l)
  470. {
  471. long x;
  472. if(read_data(s,(char *)&x,sizeof(long))==sizeof(long)) 
  473.  {
  474.    *l=ntohl(x);/* network to host long */
  475.    return 0;
  476.  }
  477. return -1;/* failed */
  478. }
  479. /*--------------------------------------------------------*/
  480. /* send a word lvalue across network              */
  481. /*--------------------------------------------------------*/
  482. int send_word(int s, short l)
  483. {
  484.    l=htons(l);/* host to network long */
  485.    if(write_data(s,(char *)&l,sizeof(long))==sizeof(long)) return 0;
  486.    return -1;/* Failed */
  487. }
  488. /*--------------------------------------------------------*/
  489. /* get  a word lvalue from network              */
  490. /*--------------------------------------------------------*/
  491. int get_word(int s, short *l)
  492. {
  493. short x;
  494. if(read_data(s,(char *)&x,sizeof(short))==sizeof(short))
  495.  {
  496.    *l=ntohs(x);/* network to host long */
  497.    return 0;
  498.  }
  499. return -1;/* failed */
  500. }
  501.  
  502. /*--------------------------------------------------------*/
  503. /* send a byte lvalue across network              */
  504. /*--------------------------------------------------------*/
  505. int send_byte(int s, char l)
  506. {
  507.    if(write_data(s,&l,sizeof(char))==sizeof(char)) return 0;
  508.    return -1;/* Failed */
  509. }
  510. /*--------------------------------------------------------*/
  511. /* get  a word lvalue from network              */
  512. /*--------------------------------------------------------*/
  513. int get_byte(int s, char *l)
  514. {
  515. if(read_data(s,l,sizeof(char))==sizeof(char))
  516.  {
  517.    return 0;
  518.  }
  519. return -1;/* failed */
  520. }
  521.  
  522. /*--------------------------------------------------------*/
  523. /* Conversation (or: How to talk between sockets)      */
  524. /* Now that you have a connection between sockets you want*/
  525. /* to send data between them. The read() and write()       */
  526. /* functions are used to do this, just as they are for      */
  527. /* normal files. There is only one major difference       */
  528. /* between socket reading and writing and file reading       */
  529. /* and writing: you don't usually get back the same number*/
  530. /* of characters that you asked for, so you must loop     */
  531. /* until you have read the number of characters that you  */
  532. /* want. A simple function to read a given number of      */
  533. /* characters into a buffer is:                  */
  534. /*--------------------------------------------------------*/
  535. int read_data(int s,char *buf,int n)
  536.   int bcount=0; /* counts bytes read */
  537.   int br=0;     /* bytes read this pass */
  538.   /* loop until full buffer */
  539.   while(bcount<n) 
  540.    { 
  541.      if ((br= read(s,buf,n-bcount)) > 0) 
  542.       {
  543.       bcount += br;                /* increment byte counter */
  544.       buf += br;                   /* move buffer ptr for next read */
  545.        }
  546.      else
  547.       if(br<0) return(-1);         /* signal an error to the caller */
  548.    }
  549.   return(bcount);
  550. }
  551. /*--------------------------------------------------------*/
  552. int write_data(int s,char *buf,int n)
  553.   int bcount=0; /* counts bytes read */
  554.   int br=0;     /* bytes read this pass */
  555.   /* loop until full buffer */
  556.   while(bcount<n) 
  557.    { 
  558.      if((br= write(s,buf,n-bcount)) > 0) 
  559.       {
  560.        bcount += br;                /* increment byte counter */
  561.        buf += br;                   /* move buffer ptr for next read */
  562.       }
  563.      else
  564.       if(br<0) return(-1);          /* signal an error to the caller */
  565.    }
  566.   return(bcount);
  567. }
  568. /*--------------------------------------------------------*/
  569. /* Determine hostent according to given name or current   */
  570. /* machine config                      */
  571. /*--------------------------------------------------------*/
  572. struct hostent *mygethostent(char *hostname)
  573. {
  574. struct hostent     *hp;
  575. static struct hostent dm;
  576. static unsigned char bf[4];
  577. static char *ls[2],myname[MAXHOSTNAME+1];
  578. char *cx;
  579. if(!hostname || !*hostname)
  580.  {
  581.   mygethostname(myname,MAXHOSTNAME);      /* who are we? */
  582.   if(hostname) strcpy(hostname,myname);
  583.   hostname=myname;
  584.  }
  585. if(*hostname>='0' && *hostname<='9')
  586.  {
  587.      char *c=hostname;
  588.      memset(bf,0,4);
  589.      /* assume dot adress */
  590.      bf[0]=atol(c);while(*c && *c!='.') c++;c++;
  591.      bf[1]=atol(c);while(*c && *c!='.') c++;c++;
  592.      bf[2]=atol(c);while(*c && *c!='.') c++;c++;
  593.      bf[3]=atol(c);
  594.      hp=&dm;
  595.      memset(hp,0,sizeof(dm));
  596.      hp->h_name=hostname;
  597.      hp->h_aliases=NULL;
  598.      hp->h_addrtype=2;
  599.      hp->h_length=4;
  600.      hp->h_addr_list=ls;
  601.      ls[0]=bf;ls[1]=NULL;
  602.    }
  603. else hp=gethostbyname(hostname);/* do we know the host's */
  604. return hp;/* return our static data */
  605. }
  606. /*--------------------------------------------------------*/
  607. /* Unlike with the telephone, you may still accept calls  */ 
  608. /* while processing previous connections. For this reason */
  609. /* you usually fork off jobs to handle  each connection.  */
  610. /* The following code shows how to use establish() and    */
  611. /* get_connection() to allow multiple connections to be   */
  612. /* dealt with:                          */
  613. /*--------------------------------------------------------*/
  614. /* wait for a connection to occur on a socket created with*/
  615. /* establish()                          *
  616. /*--------------------------------------------------------*/
  617. int get_connection(int s)
  618. int t;                  /* socket of connection */
  619. if ((t = accept(s,NULL,NULL)) < 0)   /* accept connection if there is one */
  620.     return(-1);
  621. if(sw_keepalive) sokeepalive(t);
  622. return(t);
  623. }
  624. /*--------------------------------------------------------*/
  625. /* Dialing (or: How to call a socket)              */
  626. /* You now know how to create a socket that will accept   */
  627. /*  incoming calls. So how do you call it? As with the       */
  628. /* telephone, you must first have the phone before using  */
  629. /* it  to call. You use the socket() function to do this, */
  630. /* exactly as you establish a socket to listen to.      */
  631. /* After getting a socket to make the call with, and      */
  632. /* giving it an address, you use the connect() function to*/
  633. /*  try to  connect to a listening socket. The            */
  634. /* following function calls a particular port number on a */
  635. /* particular host:                      */
  636. /*--------------------------------------------------------*/
  637. /* This function returns a connected socket through which */
  638. /*  data can flow.                      */
  639. /*--------------------------------------------------------*/
  640. int call_socket(char *hostname, unsigned short portnum)
  641. {
  642.   struct sockaddr_in sa;
  643.   struct hostent     *hp;
  644.   int a, s;
  645.   if((hp= mygethostent(hostname)) == NULL) { /* do we know the host's */
  646.     errno= ECONNREFUSED;                       /* address? */
  647.     return(-1);                                /* no */
  648.   }
  649.   memset(&sa,0,sizeof(sa));
  650.   memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length);     /* set address */
  651.   sa.sin_family= hp->h_addrtype;
  652.   sa.sin_port= htons((unsigned short)portnum);
  653.  
  654.   printf("call_socket: calling %s type=%ld %s:%ld\n",
  655.     hostname,hp->h_addrtype,dumpadr(hp->h_addr,hp->h_length),(long)portnum);
  656.  
  657.   if ((s= socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)     /* get socket */
  658.     return(-1);
  659.   if(sw_keepalive) sokeepalive(s);
  660.  
  661.   if (connect(s,(struct sockaddr *)&sa,sizeof sa) < 0) { /* connect */
  662.     close(s);
  663.     return(-1);
  664.   }
  665.   return(s);
  666. }
  667. /*--------------------------------------------------------*/
  668. /* Establish a socket; originally from bzs@bu-cs.bu.edu   */
  669. /*--------------------------------------------------------*/
  670. int establish(unsigned short portnum)
  671. {
  672.   int    s;
  673.   struct sockaddr_in sa;
  674.   struct hostent *hp;
  675.   char *cx;
  676.   static char myname[MAXHOSTNAME+1];
  677.   myname[0]=0;
  678.   if((hp= mygethostent(myname)) == NULL) { /* do we know the host's */
  679.     errno= ECONNREFUSED;                       /* address? */
  680.     return(-1);                                /* no */
  681.   }
  682.   printf("establish: %s adr type=%ld %s:%ld\n",
  683.     myname,hp->h_addrtype,dumpadr(hp->h_addr,hp->h_length),(long)portnum);
  684.   memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */
  685.   sa.sin_family= hp->h_addrtype;              /* this is our host address */
  686.   sa.sin_port= htons(portnum);                /* this is our port number */
  687.   if ((s= socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */
  688.     return(-1);
  689.   if(sw_keepalive) sokeepalive(s);
  690.  
  691.   if (bind(s,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) {
  692.     close(s);
  693.     return(-1);                               /* bind address to socket */
  694.   }
  695.   listen(s, 3);                               /* max # of queued connects */
  696.   return(s);
  697. }
  698. /*--------------------------------------------------------*/
  699. int mygethostname(char *hostname,int maxlen)
  700. {
  701. char *cx;
  702. gethostname(hostname,maxlen);           /* who are we? */
  703. /* libsocket for djgpp kludge */
  704. if(*hostname)
  705.    {
  706.      cx=hostname+strlen(hostname)-1;
  707.      while(cx>=hostname && *cx==' ') *cx--=0;
  708.    }
  709. return *hostname ? 1:-1;
  710. }
  711. /*--------------------------------------------------------*/
  712. char *dumpadr(char *s,long len)
  713. {
  714. char *c;
  715. static char buf[500];
  716. long i;
  717. //printf("dumpadr: [%08lx] %ld\n",s,len);
  718. if(len>500-1) len=500-1;
  719. for(i=0,c=buf;i<len;i++) 
  720.  {
  721.    sprintf(c,"%03ld.",(unsigned long) ((UBYTE)*s++) );c+=4;
  722.  }
  723. *--c=0;/* remove last . */
  724. return buf;
  725. }
  726. /*--------------------------------------------------------*/
  727. void memdump(void *s,long len,long adr)
  728. {
  729. UBYTE *c=s;
  730. long i;
  731. for(i=0;i<len;i+=0x10,c+=0x10,adr+=0x10) 
  732.  printf("%08lX: %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX\n",
  733.        adr,
  734.        c[0x0],c[0x1],c[0x2],c[0x3],
  735.        c[0x4],c[0x5],c[0x6],c[0x7],
  736.        c[0x8],c[0x9],c[0xa],c[0xb],
  737.        c[0xc],c[0xd],c[0xe],c[0xf]);
  738. }
  739. /*--------------------------------------------------------*/
  740. /* return hexval+1                      */
  741. /*--------------------------------------------------------*/
  742. UBYTE ishex(UBYTE c)
  743. {
  744. if((c>='0' && c<='9')) c=c-('0'-1);
  745. else
  746.  {
  747.   c|=0x20;/* lowercase */
  748.   if(c>='a' && c<='f'  ) c=c-('a'-10-1);
  749.   else c=0;
  750.  }
  751. return c;
  752. }
  753. /*--------------------------------------------------------*/
  754. long my_htol(char *s,char **ds)
  755. {
  756. register long l=0,sg;
  757. register UBYTE ch;
  758. if(*s=='-') {s++;sg=1;}else sg=0;
  759. /*----------------------------------*/
  760. /* Skip first  chars if they are    */
  761. /* '$' , '0x' or '0X'             */
  762. /*----------------------------------*/
  763. if(*s=='$') s++;
  764. if(*s=='0' && (s[1]|0x20)=='x') s+=2;
  765. while((ch=ishex(*s))!=0)
  766.  {
  767.    l=(l<<4)+(ch-1);
  768.    s++;
  769.  }
  770. if(ds) *ds=s;/* Update ptr */
  771. return sg ? -l:l;
  772. }
  773. /*--------------------------------------------------------*/
  774. long ntol(char *s)
  775. {
  776. long num;
  777. if(*s=='0' && (s[1]|0x20)=='x') num=my_htol(s,NULL);
  778. else                 num=atol(s);
  779. return num;
  780. }
  781. /*--------------------------------------------------------*/
  782. char *htoa(long n,char ln)
  783. {
  784. register char *cx,c,h;
  785. static char buf[9];
  786. if(ln==0) ln=8;
  787. buf[ln]=0;cx=buf+ln-1;
  788. for(c=ln;c;c--,n>>=4,cx--)
  789.  {
  790.    h=n&0xF;
  791.    if(h>=10) *cx=h+('A'-10);else *cx=h+'0';
  792.  }
  793. return buf;
  794. }
  795. /*--------------------------------------------------------*/
  796. /*--------------------------------------------------------*/
  797. #define TIMEOFFSET ((((1978-1970)*365+2)*24+1)*60*60) // 252464400.00000 , 0xF0C4D10
  798. #define ADJUST (4*60*60)
  799.  
  800. #if 1 //ifndef AMIGA
  801. void CurrentTime(ULONG *s,ULONG *m)
  802. {
  803. struct timeval tv;
  804. struct timezone tz;
  805. tz.tz_minuteswest=0;
  806. tz.tz_dsttime=0;
  807. gettimeofday(&tv,&tz);
  808. if(s) *s  =(ULONG)tv.tv_sec-TIMEOFFSET+ADJUST;
  809. if(m) *m  =(ULONG)tv.tv_usec;
  810. }
  811. #endif
  812.  
  813. /* Calc  *(m1)=m2-m1; */
  814. void DiffTime(ULONG *s1,ULONG *m1,ULONG s2,ULONG m2)
  815. {
  816. if(*m1>m2) {m2+=1000000L;s2--;}
  817. (*m1)=m2-*m1;
  818. (*s1)=s2-*s1;
  819. }
  820.  
  821. char *SPrintTime(ULONG s,ULONG m)
  822. {
  823. static char buf[50];
  824. ULONG day,hour,min;
  825. day  = s/(24*60*60L);s-=day*(24*60*60L);
  826. hour = s/(60*60L)   ;s-=hour*(60*60L);
  827. min  = s/60         ;s-=min*60;
  828. /* DD.HH:MM:SS.TT */
  829. sprintf(buf,"%02ld|%02ld:%02ld:%02ld.%06ld\n",
  830.     day,hour,min,s,m);
  831. return buf;
  832. }
  833.  
  834. long memrnd(void *d,long sd,long len)
  835. {
  836. UBYTE *p=d;
  837. if(sd!=-1) RangeSeed(sd);
  838. while(len--) *p++=RangeRand(256);
  839. return sd;
  840. }
  841.  
  842. void memcsum(void *d,ULONG *cs,long len)
  843. {
  844. UBYTE *p=d;
  845. ULONG c=*cs;
  846. while(len--) c+=*p++;
  847. *cs=c;
  848. }
  849. /*--------------------------------------------------------*/
  850. static unsigned long seed=0;
  851. /*--------------------------------------------------------*/
  852. unsigned long RangeSeed(unsigned long s)
  853. {
  854. unsigned long o=seed;
  855. printf("RangeSeed: 0x%08lx\n",s);
  856. seed=s;
  857. return o;
  858. }
  859. /*--------------------------------------------------------*/
  860. unsigned short int RangeRand(int d6)
  861. {
  862. unsigned long d0,d1;
  863. unsigned short int d4,d5;
  864. d5=(unsigned short int)d6;
  865. d4=d5-1;d0=seed;
  866. do
  867.  {
  868.   d1=d0;d0+=d0;
  869.   if(d0<=d1) d0^=0x1d872b41;
  870.   d4>>=1;
  871.  } while(d4);
  872. seed=d0;
  873. if(d5) 
  874.  {
  875.   d0=d5*(d0&0xFFFF);
  876.   return (unsigned short int)(d0>>16L);
  877.  }
  878. return (unsigned short int)(d0&0xFFFF);
  879. }
  880.  
  881.  
  882.  
  883. #if 0
  884. /*
  885.  
  886. A very similar function should be used to write data; we leave that function
  887. as an exercise to the reader.
  888.  
  889. Hanging Up (or: What to do when you're done with a socket)
  890.  
  891. Just as you hang up when you're through speaking to someone over the
  892. telephone, so must you close a connection between sockets. The normal
  893. close() function is used to close each end of a socket connection. If one
  894. end of a socket is closed and the other tries to write to its end, the write
  895. will return an error.
  896.  
  897. Speaking The Language (or: Byte order is important)
  898.  
  899. Now that you can talk between machines, you have to be careful what you say.
  900. Many machines use differing dialects, such as ASCII versus (yech) EBCDIC.
  901. More commonly there are byte-order problems. Unless you always pass text,
  902. you'll run up against the byte-order problem. Luckily people have already
  903. figured out what to do about it.
  904.  
  905. Once upon a time in the dark ages someone decided which byte order was
  906. "right". Now there exist functions that convert one to the other if
  907. necessary. Some of these functions are htons() (host to network short
  908. integer), ntohs() (network to host short integer), htonl() (host to network
  909. long integer), and ntohl() (network to host long integer). Before sending an
  910. integer through a socket, you should first massage it with the htonl()
  911. function:
  912.  
  913. i= htonl(i);
  914. write_data(s, &i, sizeof(i));
  915.  
  916. and after reading data you should convert it back with ntohl():
  917.  
  918. read_data(s, &i, sizeof(i));
  919. i= ntohl(i);
  920.  
  921. If you keep in the habit of using these functions you'll be less likely to
  922. goof it up in those circumstances where it is necessary.
  923.  
  924. The Future Is In Your Hands (or: What to do now)
  925.  
  926. Using just what's been discussed here, you should be able to build your own
  927. programs that communicate with sockets. As with all new things, however, it
  928. would be a good idea to look at what's already been done. While there are
  929. not a lot of books describing BSD sockets, one good reference is Unix
  930. Network Programming by W. Richard Stevens (Prentice-Hall 1990, ISBN
  931. 0-13-949876-1). In addition, you should look at some of the many
  932. public-domain applications which make use of sockets, since real
  933. applications are the best teachers. One such application is msend, a utility
  934. used to send messages between users on different hosts.
  935.  
  936. Beware that the examples given here leave out a lot of error checking which
  937. should be used in a real application. You should check the manual pages for
  938. each of the functions discussed here for further information. If you have
  939. specific questions regarding sockets, please feel free to ask me at
  940. jimf@world.std.com.
  941. */
  942.  
  943. #if 0
  944.    printf("reading 256 ..\n");
  945.    l=read_data(s,buf,256);
  946.    printf("read %d bytes.\n",l);
  947.    for(i=0,c=buf;i<l;i+=0x10,c+=0x10) 
  948.      printf("%02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX %02lX%02lX%02lX%02lX\n",
  949.        c[0x0],c[0x1],c[0x2],c[0x3],
  950.        c[0x4],c[0x5],c[0x6],c[0x7],
  951.        c[0x8],c[0x9],c[0xa],c[0xb],
  952.        c[0xc],c[0xd],c[0xe],c[0xf]);
  953.    printf("receive_data: closing socket.\n");
  954.    close(s);
  955.    printf("done.. returning.\n");
  956. #endif
  957. #endif
  958.  
  959. /*========================================================*/
  960. /*-END OF SOURCE (stest.c)      --------------------------*/
  961. /*========================================================*/
  962.  
  963.